/**
 * Author: grx
 * Description: 展示本周学习记录图表的Fragment
 */
package com.example.parallelandroid;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.example.parallelandroid.entity.StudyTimeRecord;
import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.utils.ViewPortHandler;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class WeekFragment extends Fragment {

    private static final int GET_RECORDS = 1;
    private BarChart barChart;
    private LineChart lineChart;
    private Button btnSwitch;
    private SharedPreferences chart;
    private SharedPreferences.Editor editor;
    private SharedPreferences user;
    private OkHttpClient okHttpClient;
    private  StudyTimeRecord[] records;
    private List<String> xValues; // 横坐标值
    private List<BarEntry> yValues; // 柱状图纵坐标值
    private List<Entry> yVals; // 折线图纵坐标值

    private Handler handler = new Handler(Looper.myLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case GET_RECORDS:
                    records = (StudyTimeRecord[]) msg.obj;
                    // 首次加载本页面时，默认显示柱状图
                    // 初始化柱状图
                    initBarChart(records);
                    editor.putBoolean("isBarChartWeek", true);
                    editor.commit();

                    // 给某"切换"按钮添加事件监听器
                    btnSwitch.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if (chart.getBoolean("isBarChartWeek", false)) {
                                editor.putBoolean("isBarChartWeek", false);
                                editor.commit();
                                initLineChart(records);
                            } else {
                                editor.putBoolean("isBarChartWeek", true);
                                editor.commit();
                                initBarChart(records);
                            }
                        }
                    });
                    break;
            }
        }
    };

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        // 获取SharedPreferences
        chart = getContext().getSharedPreferences("studyStatistics", Context.MODE_PRIVATE);
        editor = chart.edit();
        user = getContext().getSharedPreferences("user", Context.MODE_PRIVATE);

        // 获取布局文件
        View view = inflater.inflate(R.layout.fragment_chart, null);
        // 获取布局文件中的控件对象
        barChart = view.findViewById(R.id.barChart);
        btnSwitch = view.findViewById(R.id.btn_switch);
        lineChart = view.findViewById(R.id.lineChart);

        // 从服务端获取最近七天的学习记录
        getStudyRecordsFromServer(user.getString("userId", "userId"));

        // 返回布局文件对象
        return view;
    }

    /**
     * 从服务端获取最近七天的学习记录
     * @param userId 用户id
     */
    private void getStudyRecordsFromServer(String userId) {
        Constant.logger.info("开始从服务端获取最近七天的学习记录 userId=" + userId);
        okHttpClient = new OkHttpClient();
        // 创建请求体对象
        Request request = new Request.Builder()
                .url(Constant.BASE_URL + "studyTimeRecord/findRecord?userId=" + userId)
                .addHeader("Connection","close")
                .build();
        // 发送请求，获取响应
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                Constant.logger.warn("获取最近七天的学习记录: 失败", e);
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        // 此处执行UI操作
                        Toast.makeText(getContext(), "学习数据加载失败", Toast.LENGTH_SHORT).show();
                    }
                });
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                try {
                    String json = response.body().string();
                    JSONObject jsonObject = new JSONObject(json);
                    String msg = jsonObject.getString("msg");
                    JSONArray jsonArray = jsonObject.getJSONArray("data");
                    StudyTimeRecord[] array = new StudyTimeRecord[7];
                    for (int i = 0; i < 7; i++) {
                        JSONObject object = jsonArray.getJSONObject(i);
                        String userDateId = object.getString("userDateId");
                        String userId = object.getString("userId");
                        DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
                        Date date = fmt.parse(object.getString("studyDate"));
                        java.sql.Date studyDate = new java.sql.Date(date.getTime());
                        double studyTime = object.getDouble("studyTime");
                        array[6-i] = new StudyTimeRecord(userDateId, userId, studyDate, studyTime);
                    }
                    Message message = new Message();
                    message.what = GET_RECORDS;
                    message.obj = array;
                    handler.sendMessage(message);
                    Constant.logger.info("服务端Response: " + msg);
                } catch (JSONException e) {
                    Constant.logger.warn("解析服务端Response: 失败", e);
                } catch (ParseException e) {
                    Constant.logger.warn("解析服务端Response: 失败", e);
                }
            }
        });
    }

    // 初始化折线图
    private void initLineChart(StudyTimeRecord[] records) {
        barChart.setVisibility(View.INVISIBLE); // 设置柱状图不可见
        lineChart.setVisibility(View.VISIBLE); // 设置折线图可见
        btnSwitch.setText("切换为柱状图");
        lineChart.setTouchEnabled(false);
        lineChart.animateY(1000);
        lineChart.setExtraLeftOffset(10f);
        lineChart.setExtraRightOffset(25f);
        lineChart.getDescription().setEnabled(false);
        lineChart.setNoDataText("今天还没有学习嗷~");

        // 初始化横纵坐标值
        if (records != null) {
            xValues = initXValues(records);
            lineChart.getXAxis().setValueFormatter(new IAxisValueFormatter() {
                @Override
                public String getFormattedValue(float v, AxisBase axisBase) {
                    return xValues.get((int)v);
                }
            });
            yVals = initYVals(records);
            LineDataSet lineDataSet = new LineDataSet(yVals, "学习时长/小时");
            lineDataSet.setValueFormatter(new IValueFormatter() {
                @Override
                public String getFormattedValue(float v, Entry entry, int i, ViewPortHandler viewPortHandler) {
                    // 保留两位小数
                    NumberFormat nf = NumberFormat.getNumberInstance();
                    nf.setMaximumFractionDigits(2);
                    // 四舍五入
                    nf.setRoundingMode(RoundingMode.UP);
                    return nf.format(v);
                }
            });
            // 设置折线图的属性
            //设置线的颜色
//            lineDataSet.setColor(Color.parseColor("#ffffff"));
//            设置线的宽度
            lineDataSet.setLineWidth(2f);
            //设置每个坐标点的圆大小
//            lineDataSet.setCircleRadius(3f);
            //设置圆圈的颜色
//            lineDataSet.setCircleColor(Color.parseColor(lineList.get(j).getColor()));

            LineData lineData = new LineData(lineDataSet);
            lineData.setValueTextSize(15.0f);
            lineChart.setData(lineData);
        }

        // 绘制轴线
        drawAxis(lineChart.getXAxis()); // X轴
        drawAxis(lineChart.getAxisLeft()); // 左Y轴
        lineChart.getAxisRight().setEnabled(false); // 取消右Y轴

        Constant.logger.info("初始化折线图 完成");
    }

    // 初始化柱状图
    private void initBarChart(StudyTimeRecord[] records) {
        barChart.setVisibility(View.VISIBLE); // 设置柱状图可见
        lineChart.setVisibility(View.INVISIBLE); // 设置折线图不可见
        btnSwitch.setText("切换为折线图");
        barChart.setTouchEnabled(false);
        barChart.animateY(1000); // 设置动画
        barChart.setExtraLeftOffset(10f);
        barChart.setExtraRightOffset(10f);
        barChart.getDescription().setEnabled(false);
        barChart.setNoDataText("今天还没有学习嗷~");

        // 初始化横纵坐标值
        if (records != null) {
            xValues = initXValues(records);
            barChart.getXAxis().setValueFormatter(new IAxisValueFormatter() {
                @Override
                public String getFormattedValue(float v, AxisBase axisBase) {
                    return xValues.get((int)v);
                }
            });

            yValues = initYValues(records);
            BarDataSet barDataSet = new BarDataSet(yValues, "学习时长/小时");
            barDataSet.setValueFormatter(new IValueFormatter() {
                @Override
                public String getFormattedValue(float v, Entry entry, int i, ViewPortHandler viewPortHandler) {
                    // 保留两位小数
                    NumberFormat nf = NumberFormat.getNumberInstance();
                    nf.setMaximumFractionDigits(2);
                    // 四舍五入
                    nf.setRoundingMode(RoundingMode.UP);
                    return nf.format(v);
                }
            });
            BarData barData = new BarData(barDataSet);
            barData.setValueTextSize(15.0f);
            barChart.setData(barData);
        }

        // 绘制轴线
        drawAxis(barChart.getXAxis()); // X轴
        drawAxis(barChart.getAxisLeft()); // 左Y轴
        barChart.getAxisRight().setEnabled(false); // 取消右Y轴

        Constant.logger.info("初始化柱状图 完成");
    }

    // 绘制轴线
    private void drawAxis(AxisBase mAxis) {
        mAxis.setEnabled(true); // 是否启用轴线
        mAxis.setDrawLabels(true); // 是否开启绘制轴的标签
        mAxis.setDrawAxisLine(true); // 是否绘制轴线
//        mAxis.setDrawGridLines(true); // 绘制网格线
        if (mAxis.getClass() == XAxis.class) {// 如果是x轴
            XAxis xAxis = (XAxis)mAxis;
            xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
            xAxis.setLabelRotationAngle(30); //标签倾斜
            //设置为true当一个页面显示条目过多，X轴值隔一个显示一个
            xAxis.setGranularityEnabled(true);
        }
        if (mAxis.getClass() == YAxis.class) { // 如果是Y轴
            YAxis yAxis = (YAxis)mAxis;
            yAxis.setStartAtZero(true); // 强制Y轴从0开始
            yAxis.setLabelCount(13, true); // 强制设置标签个数
            yAxis.setAxisMaxValue(12);
        }
    }

    // 初始化纵坐标值: 折线图
    private List<Entry> initYVals(StudyTimeRecord[] records) {
        List<Entry> yVals = new ArrayList<>();
        if (records != null) {
            for (int i = 0; i < records.length; i++) {
                yVals.add(new Entry(i, (float) records[i].getStudyTime()));
            }
            return yVals;
        } else {
            return null;
        }
    }

    // 初始化纵坐标值: 柱状图
    private List<BarEntry> initYValues(StudyTimeRecord[] records) {
        List<BarEntry> yValues = new ArrayList<>();
        if (records != null) {
            for (int i = 0; i <records.length; i++) {
                yValues.add(new BarEntry(i, (float) records[i].getStudyTime()));
            }
            return yValues;
        } else {
            return null;
        }
    }

    // 初始化横坐标值
    private List<String> initXValues(StudyTimeRecord[] records) {
        List<String> xValues = new ArrayList<>();
        if (records != null) {
            for (int i = 0; i < 7; i++) {
                xValues.add(records[i].getStudyDate().toString());
            }
        }
        return xValues;
    }

}
